﻿using System;
using System.Collections.Generic;
using System.Text;

using Galaxy.ModuleInterface;
using Galaxy.ModuleInterface.Messages;
using Galaxy.ModuleInterface.Exceptions;

using Galaxy.Core.Exceptions;

namespace Galaxy.Core
{
    /// <summary>Синхронное ядро Галактики</summary>
    public partial class CGalaxyCore : CGalaxyModule, IGalaxyModule, IGalaxyCore
    {
        /* ----------------------------------------------------------------------- */

        /// <summary>Индикато проинициализированности ядра</summary>
        private bool f_Initialized = false;

        /// <summary>Индикатор активности ядра</summary>
        private bool f_Enable = false;

        /* ----------------------------------------------------------------------- */

        /// <summary>Ядро проинициализировано</summary>
        public override bool Initialized { get { return f_Initialized; } }

        /// <summary>Ядро включено</summary>
        public override bool Enable
        {
            get { return f_Enable; }
            set
            {
                if( value ) Start(); else Stop();
                base.Enable = value;
            }
        }

        /* ----------------------------------------------------------------------- */

        /// <summary>Запуск ядра</summary>
        public override void Start()
        {
            if( Enable ) return;


            if( !Initialized ) Initialize();
            for( int i = 0; i < ConnectedModules.Count; i++ )
                if( ConnectedModules[i].Initialized )
                    try { ConnectedModules[i].Start(); }
                    catch( StartException StartError )
                    {
                        InvokeOnError(new CoreStartException(
                            "Ошибка запуска модуля",
                            StartError));
                    }

            f_Enable = true;

#if DEBUG
            Console.WriteLine(Name + " запущен");
#endif
            InvokeOnEnable();
        }

        /// <summary>Остановка ядра</summary>
        public override void Stop()
        {
            if( !Enable ) return;
            f_Enable = false;

            for( int i = 0; i < ConnectedModules.Count; i++ )
                try { ConnectedModules[i].Stop(); }
                catch( StopException StopError )
                {
                    InvokeOnError(new CoreStopException(
                        "Ошибка при остановке модуля",
                        StopError));
                }

#if DEBUG
            Console.WriteLine(Name + " остановлен");
#endif
            InvokeOnEnable();
        }

        /// <summary>Инициализация ядра</summary>
        public override void Initialize()
        {
            if( Initialized ) return;
            for( int i = 0; i < ConnectedModules.Count; i++ )
                try { ConnectedModules[i].Initialize(); }
                catch( InitializationException InitializationError )
                {
                    InvokeOnError(new CoreInitializationException(
                        "Ошибка при инициализации модуля",
                        InitializationError));
                }

            f_Initialized = true;

#if DEBUG
            Console.WriteLine(Name + " проинициализирован");
#endif 
        }

        /// <summary>Обработка сообщения ядра</summary>
        /// <param name="Message">Сообщение</param>
        public override void ProcessMessage(IGalaxyModuleMessage Message)
        {
            base.ProcessMessage(Message);
        }

        /* ----------------------------------------------------------------------- */

        /// <summary>Добавить модуль в ядро</summary>
        /// <param name="Module">Добавляемый модуль</param>
        public virtual void AddModule(params IGalaxyModule[] Module)
        {
            for( int i = 0; i < Module.Length; i++ )
            {
                if( Initialized ) Module[i].Initialize();
                ConnectModule(Module[i]);
                if( Enable ) Module[i].Enable = true;
            }
        }

        /// <summary>Подключить модуль ко всем модулям ядра</summary>
        /// <param name="Module">Подключаемый модуль</param>
        protected virtual void ConnectModule(IGalaxyModule Module)
        {
            this.Connect(Module);

            for( int i = 0; i < ConnectedModules.Count; i++ )
                ConnectedModules[i].Connect(Module);
        }

        /// <summary>Удалить модуль</summary>
        /// <param name="Module">Удаляемый модуль</param>
        public virtual void RemoveModule(params IGalaxyModule[] Module)
        {
            for( int i = 0; i < Module.Length; i++ )
                DisconnectModule(Module[i]);
        }

        /// <summary>Отключить модуль от ядра</summary>
        /// <param name="Module">Отключаемый модуль</param>
        protected virtual void DisconnectModule(IGalaxyModule Module)
        {
            for( int i = 0; i < ConnectedModules.Count; i++ )
                ConnectedModules[i].Disconnect(Module);

            this.Disconnect(Module);
        }

        /* ----------------------------------------------------------------------- */
    }
}